﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Games.SeriesLights
{
    class Game
    {
        private int[,] values = new int[1, 1];
        private bool[,] status = new bool[1, 1];
        private List<int> mins = new List<int>();
        private int total;
        private int brights;

        public void Init(int width, int height)
        {
            this.width = width;
            this.height = height;
            this.total = width * height;
            this.brights = 0;
            this.values = new int[width, height];
            this.status = new bool[width, height];
            this.mins.Clear();
            var random = new Random(DateTime.Now.Millisecond);
            var series = Enumerable.Range(1, total).ToList();
            for(int x = 0; x < width; x++)
            {
                for(int y = 0; y < height; y++)
                {
                    var valIndex = random.Next(series.Count);
                    var val = series[valIndex];
                    this.values[x, y] = val;
                    series.RemoveAt(valIndex);
                }
            }
        }

        public void Click(int x, int y, Action<int, bool> bright, Action<int> show)
        {
            if(IsFinished || !InBoard(x, y))
            {
                return;
            }
            var val = GetValue(x, y);
            if(this.mins.Contains(val))
            {
                return;
            }
            status[x, y] ^= true;
            var index = x * height + y;
            if(IsBright(x, y))
            {
                var lb = this.brights;

                for(int i = 0; i < width; i++)
                {
                    for(int j = 0; j < height; j++)
                    {
                        if(IsBright(i, j) && GetValue(i, j) > val)
                        {
                            status[i, j] = false;
                            bright(i * height + j, false);
                            this.brights--;
                        }
                    }
                }
                if(lb > this.brights)
                {
                    status[x, y] = false;
                }
                else
                {
                    this.brights++;
                }
                if(IsBright(x, y))
                {
                    if(this.mins.Count == 0)
                    {
                        if(val == 1)
                        {
                            show(index);
                            this.mins.Add(val);
                        }
                    }
                    else
                    {
                        var max = this.mins.Max() + 1;
                        if(max == val)
                        {
                            show(index);
                            this.mins.Add(val);
                        }
                    }
                }
            }
            else
            {
                this.brights--;
            }
            bright(index, IsBright(x, y));
        }
        public bool InBoard(int x, int y)
        {
            if(x < 0 || x >= width)
            {
                return false;
            }
            if(y < 0 || y >= height)
            {
                return false;
            }
            return true;
        }

        public int GetValue(int x, int y)
        {
            return this.values[x, y];
        }

        public bool IsBright(int x, int y)
        {
            return this.status[x, y];
        }

        public bool IsFinished
        {
            get { return this.total == this.brights; }
        }

        private int width;
        private int height;
    }
}
